home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / bor_ti.exe / TI1031.ASC < prev    next >
Encoding:
Text File  |  1992-10-23  |  18.0 KB  |  727 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.   PRODUCT  :  Borland C++                           NUMBER  :  1031
  9.   VERSION  :  3.x
  10.        OS  :  DOS
  11.      DATE  :  October 23, 1992                        PAGE  :  1/11
  12.  
  13.     TITLE  :  Some Graphics primitives using 256-Color VGA Mode.
  14.  
  15.  
  16.  
  17.  
  18.  
  19.   //   A graphics library demonstrating the simplicity of fast
  20.   //   graphics in 320x200x256-color VGA mode.  The code is not
  21.   //   fully optimized but it is pretty close; an extra 5% or so
  22.   //   might be squeezed out of the putimage() for example.  Be
  23.   //   careful when altering pseuodoregisters; while doing one
  24.   //   load the compiler may trash another register which was just
  25.   //   loaded with something pertinent.
  26.  
  27.  
  28.   //   Functions provided include point, row, and array (image)
  29.   //   drawing functions, as well as palette functions using BIOS
  30.   //   and line-drawing and circle-drawing functions.
  31.  
  32.   //   Main() demonstrates most of the functions in a pretty and
  33.   //   interesting way.
  34.  
  35.  
  36.   void GrInit(void);
  37.   void GrClose(void);
  38.   unsigned char GetPixel(unsigned int x, unsigned int y);
  39.   void PutPixel(unsigned int x, unsigned int y, unsigned char
  40.   color);
  41.   void FillRow(unsigned x, unsigned y, unsigned char color,
  42.   unsigned length);
  43.   void PutRow(unsigned x, unsigned y, char *data, unsigned length);
  44.   void GetRow(unsigned x, unsigned y, char *data, unsigned length);
  45.   void PutImage(unsigned x, unsigned y, char *data, unsigned rows,
  46.   unsigned cols);
  47.   void GetImage(unsigned x, unsigned y, char *data, unsigned rows,
  48.   unsigned cols);
  49.   void GetAllPalette(char (*palette)[3]);
  50.   void SetAllPalette( char (*palette)[3]);
  51.   void Circle(int x, int y, int radius, unsigned char color);
  52.   void Line(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
  53.             unsigned char color);
  54.  
  55.  
  56.  
  57.   #define VIDEOINT 0x10
  58.  
  59.   #pragma inline
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.   PRODUCT  :  Borland C++                           NUMBER  :  1031
  75.   VERSION  :  3.x
  76.        OS  :  DOS
  77.      DATE  :  October 23, 1992                        PAGE  :  2/11
  78.  
  79.     TITLE  :  Some Graphics primitives using 256-Color VGA Mode.
  80.  
  81.  
  82.  
  83.  
  84.   // 'dos.h' is essential
  85.   #include <dos.h>
  86.   // we need 'math.h' for sqrt() in Circle() and abs() in Line()
  87.   #include <math.h>
  88.   // we need 'conio.h' for getch()
  89.   #include <conio.h>
  90.  
  91.   int rowOffset[200];  // as an optimization,
  92.                        // rowOffset will be used as a table to
  93.                        // avoid the multiplication column+(320*row)
  94.                        // when getting the actual memory address of
  95.                        // a pixel or a row
  96.  
  97.  
  98.  
  99.   //   GrInit() initializes the rowOffset table and switches video
  100.   //   modes to 320x200 with 256 colors
  101.   void GrInit()
  102.   {
  103.        int i;
  104.        // Pre-setup our multipications for column,
  105.        //row -> screen address
  106.        for (i=0; i<200; ++i)
  107.        {
  108.             rowOffset[i]=i*320;
  109.        }
  110.        // Set video mode to 320x200 --
  111.        // sophisticated users may wish to research checking
  112.        // for the availability of VGA/MCGA prior to switching
  113.        // modes.
  114.  
  115.        _AH=0;
  116.        _AL=0x13;
  117.        geninterrupt(VIDEOINT);
  118.   }
  119.  
  120.  
  121.  
  122.   // GrClose sets the video back into text mode
  123.   void GrClose()
  124.   {
  125.        //   set video mode 80x25 color text -- we're assuming
  126.        //   that that's available
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.   PRODUCT  :  Borland C++                           NUMBER  :  1031
  141.   VERSION  :  3.x
  142.        OS  :  DOS
  143.      DATE  :  October 23, 1992                        PAGE  :  3/11
  144.  
  145.     TITLE  :  Some Graphics primitives using 256-Color VGA Mode.
  146.  
  147.  
  148.  
  149.  
  150.        //   if we're using VGA
  151.        _AH=0;
  152.        _AL=0x3;
  153.        geninterrupt(VIDEOINT);
  154.   }
  155.  
  156.  
  157.  
  158.   //   GetPixel returns the pixel value at a given (x,y) screen
  159.   //   location
  160.   unsigned char GetPixel(unsigned int x, unsigned int y)
  161.   {
  162.        return *((char far *) 0xA0000000L+ (x+rowOffset[y]));
  163.   }
  164.  
  165.  
  166.  
  167.   //   PutPixel changes the pixel at a given (x,y) screen location
  168.   //   to value 'color'
  169.   void PutPixel( unsigned int x, unsigned int y,
  170.                  unsigned char color)
  171.   {
  172.        *((char far *) 0xA0000000L + (x+rowOffset[y]))=color;
  173.   }
  174.  
  175.  
  176.  
  177.   //   FillRow writes a row of 'color' color pixels of length
  178.   //   'length' starting at screen location (x,y).
  179.   void FillRow(  unsigned x, unsigned y, unsigned char color,
  180.                  unsigned length )
  181.   {
  182.        _ES=0xA000;           // The segment for screen memory
  183.        _DI=x+rowOffset[y];   // The offset in screen to write at
  184.        _CX=length;           // Number of bytes for rep stosb
  185.        _AL=color;            // The value stosb will store in video
  186.                              // memory
  187.        asm {
  188.                  cld         // set direction flag so DI
  189.                              // will increment
  190.                  rep stosb   // zap a row of color AL out to
  191.                              // video memory al->[es:di]
  192.            }
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.   PRODUCT  :  Borland C++                           NUMBER  :  1031
  207.   VERSION  :  3.x
  208.        OS  :  DOS
  209.      DATE  :  October 23, 1992                        PAGE  :  4/11
  210.  
  211.     TITLE  :  Some Graphics primitives using 256-Color VGA Mode.
  212.  
  213.  
  214.  
  215.  
  216.   }
  217.  
  218.  
  219.  
  220.   //   PutRow transfers a row of pixels from 'data' to screen
  221.   //   starting at (x,y) and continuing for 'length'.  A rep
  222.   //   movsw instead of rep movsb might optimize this slightly for
  223.   //   even-length rows
  224.   void PutRow(unsigned x, unsigned y, char *data, unsigned length)
  225.   {
  226.   //   You may remove all lines marked with '***' if 'data' is a
  227.   //   near pointer (i.e. if 'data' was not allocated from the far
  228.   //   heap and was not declared as 'far' data.)  Remove them all
  229.   //   if you remove any.
  230.  
  231.        _ES=0xA000;
  232.        _DI=x+rowOffset[y];      //   the offset in video memory for
  233.                                 //   the row start
  234.        _SI=FP_OFF(data);
  235.                                 // load AX last since many C
  236.                                 // instructions will trash AX
  237.        _AX=FP_SEG(data);        // store data's segment in AX for
  238.                                 // now         ***
  239.        asm  {
  240.                  push ds        // Save DS since we're going to
  241.                                 // alter it    ***
  242.                  mov ds,ax      // load register from AX (loaded
  243.                                 //  above)     ***
  244.                  mov cx,length  // we're moving 'length' bytes
  245.                                 // total
  246.                  cld            // clear the direction flag to
  247.                                 // increment si and di
  248.                  rep movsb      // dump the whole row out to video
  249.                                 // memory [ds:si]->[es:di]
  250.                  pop ds         // Restore DS  ***
  251.             }
  252.   }
  253.  
  254.  
  255.  
  256.   //   GetRow() copies a row of pixels of length 'length' out of
  257.   //   video memory into the buffer at 'data'.  rep movsw might be
  258.   //   slightly faster here also.
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.   PRODUCT  :  Borland C++                           NUMBER  :  1031
  273.   VERSION  :  3.x
  274.        OS  :  DOS
  275.      DATE  :  October 23, 1992                        PAGE  :  5/11
  276.  
  277.     TITLE  :  Some Graphics primitives using 256-Color VGA Mode.
  278.  
  279.  
  280.  
  281.  
  282.   void GetRow(unsigned x, unsigned y, char *data, unsigned length)
  283.   {
  284.        _SI=x+rowOffset[y];      // the offset in video memory for
  285.                                 // the row start
  286.        _ES=FP_SEG(data);        // set up ES:DI to point to data
  287.        _DI=FP_OFF(data);
  288.        _AX=0xA000;              // load video segment in AX
  289.        asm  {
  290.                  push ds        // save DS since we have to use DS
  291.                                 // for copying
  292.                  mov ds,ax      // load DS with segment for video
  293.                                 // memory from AX (0xA000)
  294.                  mov cx,length  // we're moving 'length' bytes
  295.                                 // total
  296.                  cld            // clear the direction flag to
  297.                                 // increment si and di
  298.                  rep movsb      // get the whole row from video
  299.                                 // memory [ds:si]->[es:di]
  300.                  pop ds         // Restore DS
  301.             }
  302.   }
  303.  
  304.  
  305.  
  306.   //   GetImage() uses repeated GetRow's to store a screen image
  307.   //   in buffer at 'data'
  308.   void GetImage( unsigned x, unsigned y, char *data, unsigned
  309.                  columns, unsigned rows)
  310.   {
  311.        int i;
  312.        for (i=0; i<rows; ++i)
  313.        {
  314.             GetRow(x,y+i,data,columns);
  315.             data+=columns;
  316.        }
  317.   }
  318.  
  319.  
  320.  
  321.   //   PutImage() uses repeated PutRow's to display a screen image
  322.   //   from 'data' buffer
  323.   void PutImage( unsigned x, unsigned y, char *data,
  324.                  unsigned columns, unsigned rows)
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.   PRODUCT  :  Borland C++                           NUMBER  :  1031
  339.   VERSION  :  3.x
  340.        OS  :  DOS
  341.      DATE  :  October 23, 1992                        PAGE  :  6/11
  342.  
  343.     TITLE  :  Some Graphics primitives using 256-Color VGA Mode.
  344.  
  345.  
  346.  
  347.  
  348.   {
  349.        int i;
  350.        for (i=0; i<rows; ++i)
  351.        {
  352.             PutRow(x,y+i,data,columns);
  353.             data+=columns;
  354.        }
  355.   }
  356.  
  357.  
  358.  
  359.   //   traceWait() loops doing in-ports from port 0x3DA until bit 3
  360.   //   of the value read changes from 1 to 0, meaning a vertical
  361.   //   retrace just started.
  362.   void traceWait()
  363.   {
  364.     retracewait1:
  365.        asm {
  366.             mov  dx,0x3DA
  367.             in   al,dx
  368.             and  al,8
  369.             jnz  retracewait1
  370.        }
  371.     retracewait2:
  372.        asm {
  373.             mov  dx,0x3DA
  374.             in   al,dx
  375.             and  al,8
  376.             jz   retracewait2
  377.        }
  378.   }
  379.  
  380.  
  381.  
  382.   //   SetAllColors:  sets the whole range of palette registers
  383.   //   from an array containing R,G,B values
  384.   void SetAllColors(char (*palette)[3])
  385.   {
  386.        int paletteSegment,paletteOffset;
  387.        traceWait();             // if we change the palette
  388.                                 //   while the screen is being
  389.                                 // drawn, parts will appear in the
  390.                                 // old colors and parts in the new
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.   PRODUCT  :  Borland C++                           NUMBER  :  1031
  405.   VERSION  :  3.x
  406.        OS  :  DOS
  407.      DATE  :  October 23, 1992                        PAGE  :  7/11
  408.  
  409.     TITLE  :  Some Graphics primitives using 256-Color VGA Mode.
  410.  
  411.  
  412.  
  413.  
  414.                                 // and this will look odd.  So wait
  415.                                 // for vert. retrace!
  416.        _ES=FP_SEG(palette);     // load ES:DX with palette's
  417.                                 // address
  418.        _DX=FP_OFF(palette);
  419.        _AX=0x1012;              // service 0x10 subservice 0x12
  420.        _BX=0;                   // starting register
  421.        _CX=256;                 // number of registers (256 = all)
  422.        geninterrupt(VIDEOINT);
  423.   }
  424.  
  425.  
  426.  
  427.   void GetAllColors(char (*palette)[3])
  428.   {
  429.        _ES=FP_SEG(palette);     // load ES:DX with palette's
  430.                                 // address
  431.        _DX=FP_OFF(palette);
  432.        _AX=0x1017;              // service 0x10 subservice 0x17
  433.        _BX=0;                   // starting register
  434.        _CX=256;                 // number of registers (256 = all)
  435.        geninterrupt(VIDEOINT);
  436.   }
  437.  
  438.  
  439.  
  440.   //   Line takes starting and ending coordinates and a color, and
  441.   //   draws a line using Bresenham's line drawing algorithm.  The
  442.   //   algorithm uses long ints like ints that also have 16 bits of
  443.   //   precision after the decimal point.
  444.   //   Bresenham's assigns an increment of +/- 1.0 to whatever
  445.   //   variable X or Y has the greater difference and assigns some
  446.   //   increment smaller than 1 to the axis with a smaller
  447.   //   differential.  Then the line is drawing by successively
  448.   //   incrementing X and Y from the start until the end is
  449.   //   reached, and rounding each value to the nearest pixel.
  450.   void Line(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
  451.             unsigned char color)
  452.   {
  453.        long xDiff,yDiff,xInc,yInc,x,y;
  454.        int screenX,screenY;
  455.        xDiff=((long) abs(x1-x2)) << 16;
  456.        yDiff=((long) abs(y1-y2)) << 16;
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.   PRODUCT  :  Borland C++                           NUMBER  :  1031
  471.   VERSION  :  3.x
  472.        OS  :  DOS
  473.      DATE  :  October 23, 1992                        PAGE  :  8/11
  474.  
  475.     TITLE  :  Some Graphics primitives using 256-Color VGA Mode.
  476.  
  477.  
  478.  
  479.  
  480.        if (xDiff>yDiff)
  481.        {
  482.             xInc=1L<<16; yInc=yDiff/(xDiff>>16);
  483.        }
  484.        else
  485.        {
  486.             xInc=xDiff/(yDiff>>16); yInc=1L<<16;
  487.        }
  488.        if (x2 < x1) xInc= -xInc;
  489.        if (y2 < y1) yInc= -yInc;
  490.        x=((long) x1) << 16;  y=((long) y1) << 16;
  491.        do
  492.        {
  493.             screenX=(x+32767L)>>16;  screenY=(y+32767L)>>16;
  494.             PutPixel(screenX,screenY,color);
  495.             x+=xInc; y+=yInc;
  496.        } while (screenX!=x2 || screenY!=y2);
  497.        PutPixel(x2,y2,color);   // wrap up the line else we will be
  498.                                 // stopping one pixel before the
  499.                                 // end
  500.   }
  501.  
  502.  
  503.  
  504.   // Just for fun, a slightly optimized circle drawing routine
  505.   void Circle(int centerX, int centerY, int radius, unsigned char
  506.   color)
  507.   {
  508.        int i,newY,radiusSquared,distance;
  509.        radiusSquared=radius*radius;
  510.        //   sqrt(2)/2*radius is the horizontal or vertical portion
  511.        //   of 1/8 circle
  512.  
  513.        distance=sqrt(2.0)/2.0*radius;
  514.  
  515.        // as an optimization, we will just do 1/8 of a circle and
  516.        // do 7 other pixels as reflections, since a circle has
  517.        // 8-way symmetry -- all those SQRT's
  518.        // can take time!  Superfast SQRT's might be done with a
  519.        // lookup table.
  520.  
  521.        for (i=0; i<=distance; ++i)
  522.        {
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.   PRODUCT  :  Borland C++                           NUMBER  :  1031
  537.   VERSION  :  3.x
  538.        OS  :  DOS
  539.      DATE  :  October 23, 1992                        PAGE  :  9/11
  540.  
  541.     TITLE  :  Some Graphics primitives using 256-Color VGA Mode.
  542.  
  543.  
  544.  
  545.  
  546.             // the formula for a circle is x^2+y^2=radius^2
  547.             newY=sqrt(radiusSquared-i*i);
  548.             PutPixel(centerX+i, centerY+newY,color);
  549.             PutPixel(centerX-i, centerY-newY,color);
  550.             PutPixel(centerX+i, centerY-newY,color);
  551.             PutPixel(centerX-i, centerY+newY,color);
  552.             PutPixel(centerX+newY,centerY+i,color);
  553.             PutPixel(centerX-newY,centerY-i,color);
  554.             PutPixel(centerX+newY,centerY-i,color);
  555.             PutPixel(centerX-newY,centerY+i,color);
  556.        }
  557.   }
  558.  
  559.  
  560.  
  561.   #define ROWSIZE 34
  562.   char logo[5][ROWSIZE]=
  563.   {
  564.        1,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,1,0,1,1,1,0,
  565.        1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,1,0,1,0,1,0,0,1,
  566.        1,1,1,0,0,1,0,0,1,0,1,1,1,0,0,1,0,0,0,0,1,1,1,1,0,1,0,1,1,0,1,0,0,1,
  567.        1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,
  568.        1,1,1,0,0,0,1,1,0,0,1,0,0,1,0,1,1,1,1,0,1,0,0,1,0,1,0,0,1,0,1,1,1,0
  569.   };
  570.  
  571.  
  572.  
  573.   char image[2700];
  574.  
  575.  
  576.  
  577.   int main()
  578.   {
  579.        int i,j, k;
  580.        char palette[256][3], tempRed, tempGreen, tempBlue;
  581.        char *temp,color;
  582.        GrInit();
  583.  
  584.        // Demonstrate Line function
  585.        i=15;
  586.        for (j=199; j>0; j-=10)
  587.        {
  588.             Line(0,j,i,0,j/10+16);
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.   PRODUCT  :  Borland C++                           NUMBER  :  1031
  603.   VERSION  :  3.x
  604.        OS  :  DOS
  605.      DATE  :  October 23, 1992                       PAGE  :  10/11
  606.  
  607.     TITLE  :  Some Graphics primitives using 256-Color VGA Mode.
  608.  
  609.  
  610.  
  611.  
  612.             i += 16 ;
  613.        }
  614.  
  615.        // Demonstrate FillRow function with a series of rows.
  616.        for (i=92; i<=108; i+=2)
  617.        {
  618.             FillRow(136,i,7,49);
  619.        }
  620.  
  621.        // Put BORLAND logo down
  622.        PutImage(145,98,&(logo[0][0]),ROWSIZE,5);
  623.  
  624.        // Draw a circle around it
  625.        Circle(160,100,25,3);
  626.        getch();                 // pause to let the user admire our
  627.                                 // work!
  628.  
  629.        // and now some fancy stuff;
  630.        // we will get the image and 'shade' it by incrementing the
  631.        // color according to the column+row
  632.        GetImage(134,74,image,52,52);
  633.        temp=image;
  634.        for (i=0; i<52; ++i)
  635.        {
  636.             for (j=0; j<52; ++j)
  637.             {
  638.                  if (*temp!=0)
  639.                  {
  640.                       // change BORLAND to 128 higher for contrast
  641.                       if (*temp==1)
  642.                            *temp=(*temp+i+j+128)%256;
  643.                       else
  644.                            *temp=(*temp+i+j)%256;
  645.                  }
  646.                  ++temp;
  647.             }
  648.        }
  649.        // put the altered image back down
  650.        PutImage(134,74,image,52,52);
  651.        GetAllColors(palette);
  652.        // now we'll 'rotate' the palette by 1 forever, by copying
  653.        // all the colors down to the next lower color, until a key
  654.        // is hit.  Palette entry 0 is not altered, otherwise the
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668.   PRODUCT  :  Borland C++                           NUMBER  :  1031
  669.   VERSION  :  3.x
  670.        OS  :  DOS
  671.      DATE  :  October 23, 1992                       PAGE  :  11/11
  672.  
  673.     TITLE  :  Some Graphics primitives using 256-Color VGA Mode.
  674.  
  675.  
  676.  
  677.  
  678.        // background for the whole screen would be flashing.
  679.        while (!kbhit())
  680.        {
  681.             tempRed=palette[1][0]; tempGreen=palette[1][1];
  682.             tempBlue=palette[1][2];
  683.             for (j=2; j<256; ++j)
  684.             {
  685.                  for (k=0; k<3; ++k) palette[j-1][k]=palette[j][k];
  686.             }
  687.             palette[255][0]=tempRed; palette[255][1]=tempGreen;
  688.             palette[255][2]=tempBlue;
  689.             delay(15);
  690.             SetAllColors(palette);
  691.        }
  692.        GrClose();
  693.        return(0);
  694.   }
  695.  
  696.  
  697.  
  698.   DISCLAIMER: You have the right to use this technical information
  699.   subject to the terms of the No-Nonsense License Statement that
  700.   you received with the Borland product to which this information
  701.   pertains.
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.